package com.bifrost.service;

import com.bifrost.entity.Order;
import com.bifrost.entity.Product;
import com.bifrost.entity.ProductSku;
import com.bifrost.exception.InventoryUnavailableException;

import java.util.Collection;
import java.util.Map;

/**
 * @author joewee
 * @date 2017/11/15
 */
public interface InventoryService {

    /**
     * Used as a key in the context map methods below. This is used for the current order that should be used to evaluate
     * the methods below
     */
    public static String ORDER_KEY = "ORDER";

    /**
     * Used as a key in the context map methods below. This is used for the newly created change order that should be used
     * in evaluation of the below
     */
    public static String CHANGE_ORDER_KEY = "CHANGE_ORDER";

    /**
     * Used as a key in the context map methods below. This key is normally populated from the DecrementInventoryActivity
     * and is utilized in the DecrementInventoryRollbackHandler. This can be cast to a Map<String, Object> and is
     * designed such that when it is used, non-read operations (decrement and increment) can add what actually happened
     * so that it can be reversed.
     */
    public static String ROLLBACK_STATE_KEY = "ROLLBACK_STATE";

    /**
     * 订单类型
     */
    public static String ORDER_TYPE = "ORDER_TYPE";

    /**
     * 通过Sku获取 库存
     *
     * @param skuId skuId
     * @return Long
     */
    Integer getInventoryBySkuId(Long skuId);


    void decrementInventory(ProductSku sku, int quantity) throws InventoryUnavailableException;


    void decrementInventory(Map<ProductSku, Integer> skuQuantities) throws InventoryUnavailableException;


    void incrementInventory(ProductSku sku, int quantity);


    void incrementInventory(Map<ProductSku, Integer> skuQuantities);


    void decrementInventory(ProductSku sku, int quantity, Map<String, Object> context) throws InventoryUnavailableException;

    /**
     * 扣减库存
     *
     * @param inventoryToDecrement
     * @param contextualInformation
     * @throws InventoryUnavailableException
     */
    void decrementInventory(Map<ProductSku, Integer> inventoryToDecrement, Map<String, Object> contextualInformation) throws InventoryUnavailableException;

    /**
     * 检索可用库存
     * @param sku
     * @param context
     * @return
     */
    Integer retrieveQuantityAvailable(ProductSku sku, Map<String, Object> context);

    Map<ProductSku, Integer> retrieveQuantitiesAvailable(Collection<ProductSku> skus, Map<String, Object> context);

    Map<ProductSku, Integer> buildSkuInventoryMap(Order order);

    /**
     * 检查库存是否可用
     *
     * @param sku
     * @return
     */
    boolean checkBasicAvailablility(ProductSku sku);

    /**
     * 查询基本库存
     *
     * @param sku
     * @return
     */
    boolean checkInventory(ProductSku sku);


    void incrementInventory(ProductSku sku, int quantity, Map<String, Object> context);


    void incrementInventory(Map<ProductSku, Integer> skuQuantities, Map<String, Object> context);

    /**
     * 查询商品所有库存
     * @param product
     * @return
     */
    Integer retrieveQuantityAvailable(Product product);

}
